﻿using MongoDB.Driver;
using Sustainalytics.Auth.Claims;
using Sustainalytics.BusinessResearchProductStates.Entities.ResearchState;
using Sustainalytics.Claims;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.DataLayer;
using Sustainalytics.Entities.SustainableProducts;
using Sustainalytics.SustainableProducts.Service.Controllers.Helpers;
using Sustainalytics.Utils;
using Sustainalytics.Utils.WebApi.ErrorCodes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Web.Http;
using System.Web.Http.Cors;

namespace Sustainalytics.SustainableProducts.Service.Controllers
{
    [EnableCors(origins: "*", headers: "*", methods: "*")]
    //[AutoInvalidateCacheOutput]
    [RoutePrefix("api/v1/companyassessments")]
    [LogControllerFilter(true, true, false)]
    public class CompanyAssessmentController : ApiController, ICompanyAssessmentController
    {
        private readonly IClaimsChecker _claimsChecker;
        private readonly IEnumerable<SustainableProductsFramework> _spIndicators;
        private readonly IEnumerable<string> _spIndicatorSymbols;
        private readonly IMongoCollection<CorporateData> _corporateDataCollection;
        private readonly IMongoCollection<SustainableProductsData> _sustainableProductsData;
        private readonly string _routeKey;

        public CompanyAssessmentController(
            IClaimsChecker claimsChecker,
            IMongoCollection<SustainableProductsData> sustainableProductsData,
            IMongoCollection<SustainableProductsFramework> frameworkCollection,
            IMongoCollection<CorporateData> corporateDataCollection)
        {
            _claimsChecker = claimsChecker;
            _routeKey = "sp";
            _corporateDataCollection = corporateDataCollection;
            _sustainableProductsData = sustainableProductsData;
            _spIndicators = frameworkCollection.Find(_ => true).ToList();
            _spIndicatorSymbols = _spIndicators.Select(x => x.Symbol.ToLower());

        }

        [Route("{companyId}")]
        public HttpResponseMessage Get(Guid companyId)
        {
            try
            {
                List<int> userUniverseIds = ClaimsPrincipal.Current.Claims.GetUniverseIds(AccountFeature.SustainableProducts);
                List<string> claimedIndicators = _claimsChecker.GetClaimedCompanyIndicators(this, _spIndicatorSymbols, _routeKey);

                //Validate Claims Checker
                if (!claimedIndicators.Any())
                    return Request.CreateResponse(HttpStatusCode.Unauthorized);

                var corpData = _corporateDataCollection
                    .Find(cd => cd.Id == companyId && cd.ResearchParentId == null
                        && cd.SolutionsResearchState.ResearchState == ResearchState.ResearchAvailable
                        && cd.SolutionsResearchState.ClientFacingProducts.Contains(ClientFacingProduct.GA))
                    .Project<CorporateData>(Builders<CorporateData>.Projection
                        .Include(x => x.Id)
                        .Include(x => x.UniverseIds))
                    .SingleOrDefault();

                if (corpData == null)
                    return Request.CreateErrorResponse(HttpStatusCode.NotFound, $"Company with id: {companyId} not found.");

                if (corpData.UniverseIds == null || !corpData.UniverseIds.Any(x => userUniverseIds.Contains(x)))
                    throw new SPCompanyAssessmentNotInUniversesException();

                var companyAssessment = _sustainableProductsData
                    .Find(x => x.Id == companyId)
                    .SingleOrDefault();

                if (companyAssessment == null)
                    return Request.CreateErrorResponse(HttpStatusCode.NotFound, $"Data for company with id: {companyId} not found.");

                SPCompanyAssessmentDto result = SPCompanyAssessmentDto.FromCompanyAssessment(companyAssessment, _spIndicators, claimedIndicators);
                return Request.CreateResponse(HttpStatusCode.OK, result);

            }
            catch (Exception exc)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, new { ErrorStatusCode = WebAPIGeneralErrorCodes.UnhandledException });
            }
        }

        [Route("")]
        public HttpResponseMessage Get(bool getIndustries = false, bool getIndicators = false)
        {
            HttpResponseMessage response = new HttpResponseMessage();
            try
            {
                if (getIndicators)
                {
                    var claimedIndicators = _claimsChecker.GetClaimedCompanyIndicators(this, _spIndicatorSymbols, _routeKey);

                    response = Request.CreateResponse(HttpStatusCode.OK, _spIndicators.Select(x => new
                    {
                        x.Id,
                        x.Name,
                        x.Symbol,
                        x.Categories,
                        HasAccess = claimedIndicators.Contains(x.Symbol)
                    }).OrderBy(x=>x.Name));

                }
                else if (getIndustries)
                {
                    var idustries = _corporateDataCollection.AsQueryable().Select(x => new
                    {
                        Id = x.SubPeerGroupId,
                        Name = x.SubPeerGroup
                    }).Distinct().OrderBy(x=>x.Name);
                    response = Request.CreateResponse(HttpStatusCode.OK, idustries);
                }
            }
            catch (Exception ex)
            {
                response = Request.CreateResponse(HttpStatusCode.InternalServerError, new { ErrorStatusCode = WebAPIGeneralErrorCodes.UnhandledException });
            }
            return response;
        }

        //[Route("export")]
        public HttpResponseMessage Post([FromBody] string exportDetailsJsonString)
        {
            HttpResponseMessage response;
            response = Request.CreateResponse(HttpStatusCode.OK);

            return response;
        }

    }
}
